#pragma once
#include <matsu.h>
#include <string>
#include <vector>
#include "SRGLinc.h"

#if _GLES2
namespace sora
{
	class Shader;
	class ShaderProgram;

	class Camera;
	class Vertex2;
	class VertexBufferObject;
	class IndexBufferObject;

	class ShaderLocation {
	public:
		ShaderLocation(const char *name, GLint location, GLint size, GLenum type);

		const std::string &name() const;
		GLint location() const;
		GLint size() const;
		GLenum type() const;

		std::string str() const;

	private:
		std::string name_;
		GLint location_;
		GLint size_;
		GLenum type_;
	};

	class Shader {
	public:
		Shader(GLint type, const char *src);
		Shader(GLint type, const std::string &src);
		virtual ~Shader();
		GLuint handle() const;
		GLint type() const;

		static Shader *createVertShader(const std::string &src);
		static Shader *createFragShader(const std::string &src);
	private:
		void load(const std::string &src);
		GLuint handle_;
		GLint type_;
	};

	class ShaderProgram {
	public:
		ShaderProgram(Shader *vertShader, Shader *fragShader);
		ShaderProgram(const std::string &vertSrc, const std::string &fragSrc);
		virtual ~ShaderProgram();

		void setVertShader(Shader *vertShader);
		void setFragShader(Shader *fragShader);
		bool setShader(Shader *vertShader, Shader *fragShader);
		bool validate();
		bool link();
		GLuint handle() const;

		void bindAttribLocation(GLuint index, const char* name) const;
		GLuint getAttribLocation(const char* name) const;
		GLuint getUniformLocation(const char* name) const;

		std::vector<ShaderLocation> uniformLocationList() const;
		std::vector<ShaderLocation> attributeLocationList() const;

		/*
		void applyCamera(const Camera &cam) const;
		void applyModelview(const matsu::mat4 &m) const;

		//vertex2
		void applyVertex2AttribArray(const Vertex2 *vertices, int vertexCount, GLenum drawMode) const;
		void applyVertex2Index(const Vertex2 *vertices, const GLvoid *indices, int indexCount, GLenum drawMode, GLenum indexType) const;
		void applyVBO2(const VertexBufferObject &vertexbuffer, const IndexBufferObject &indexbuffer);
		*/

		void use() const;

	private:
		bool init();

		GLuint program_;
		std::auto_ptr<Shader> vShader_;
		std::auto_ptr<Shader> fShader_;
	};

	class ShaderProgramHelper {
	public:
		static void printShaderProgramLocation(const ShaderProgram &prog);
	};
}
#endif